package com.amat0urheu.service.impl;


import com.amat0urheu.dao.*;
import com.amat0urheu.pojo.*;
import com.amat0urheu.pojo.CloudPojo.OpenStack;
import com.amat0urheu.pojo.CloudPojo.RaceVm;
import com.amat0urheu.pojo.CloudPojo.VMservice;
import com.amat0urheu.pojo.CloudPojo.VmFlag;
import com.amat0urheu.pojo.race.FlagLog;
import com.amat0urheu.pojo.race.Race;
import com.amat0urheu.pojo.race.RaceParticipant;
import com.amat0urheu.pojo.race.TeamRank;
import com.amat0urheu.service.RaceService;
import com.amat0urheu.util.CommonUtil;
import com.amat0urheu.utils.CloudUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.*;


@Service
public class RaceServiceImpl implements RaceService {
    final RaceMapper raceMapper;
    final RaceParticipantMapper raceParticipantMapper;
    final UserMapper userMapper;
    final TeamMapper teamMapper;
    @Autowired
    VmMapper vmMapper;
    @Autowired
    SceneMapper sceneMapper;
    @Autowired
    CloudMapper cloudMapper;
    @Autowired
    ImageMapper imageMapper;
    @Autowired
    public RaceServiceImpl(RaceMapper raceMapper, RaceParticipantMapper raceParticipantMapper, UserMapper userMapper, TeamMapper teamMapper) {
        this.raceMapper = raceMapper;
        this.raceParticipantMapper = raceParticipantMapper;
        this.userMapper = userMapper;
        this.teamMapper = teamMapper;
    }

    @Override
    public ReturnRes getRaceView(int pageSize, int pageNum) {
        PageHelper.startPage(pageNum, pageSize);
        List<Race> raceList = raceMapper.selectAllRace();
        if (raceList != null) {
            return new ReturnRes(true, new PageInfo<>(raceList), "查询成功");
            }
        return new ReturnRes(false, "查询失败");
        }
    @Override
    public ReturnRes getRaceViewforUser(Integer pageSize, Integer pageNum) {
        PageHelper.startPage(pageNum, pageSize);
        List<Race> raceList = raceMapper.selectAllRaceforUser();
        if (raceList != null) {
            return new ReturnRes(true, new PageInfo<>(raceList), "查询成功");
        }
        return new ReturnRes(false, "查询失败");
    }

    @Override
    public ReturnRes getEndRaceForUser(Integer pageSize, Integer pageNum) {
        PageHelper.startPage(pageNum, pageSize);
        List<Race> raceList = raceMapper.getEndRaceForUser();
        if (raceList != null) {
            return new ReturnRes(true, new PageInfo<>(raceList), "查询成功");
        }
        return new ReturnRes(false, "查询失败");
    }

    @Override
    public ReturnRes getuserParticipated(Integer rid,String  user) {
       int count = raceParticipantMapper.getuserParticipated(rid,user);
       if(count>0){
           return new ReturnRes(true, "userHadParticipated");
       }
        return new ReturnRes(false, "noParticipated");
    }

    @Override
    public ReturnRes joinRace(Integer rid, String name) {

        try {
            String teamName=teamMapper.getTeamName(name);
            if(teamName==null){
                return new ReturnRes(false, "请先组队");
            }
            String tcaptain= teamMapper.getTcaptain(teamName);
            String role="队员";
            if(name.equals(tcaptain)){
                role="队长";
            }
            int count = raceMapper.getIfExitTeam(teamName,rid);
            if(count==1){
                //队伍已存在不进行任何操作
            }else {
                //将队伍插入排名中
                raceMapper.addTeamRanking(teamName ,rid);
                Integer teamNum= teamMapper.getTeanCount(rid);
            }
            raceParticipantMapper.takePartInRace(rid,name,teamName,role);
            return new ReturnRes(true, "比赛参加成功");
        }catch (Exception e){
            System.err.println(e);
            return new ReturnRes(false, "参加失败，请联系老师");
        }

//        }
    }

    @Override
    public ReturnRes getRaceVmofTeam(String name,Integer rid) {
        //获得队伍名称
        String teamName = teamMapper.getTeamName(name);
        String race =raceMapper.getRaceName(rid);
        //通过队伍名称查询小组的服务器
        List<VMservice> raceVmOfTeam= raceMapper.getRaceVmByTeamName(teamName,name,race);
        if(raceVmOfTeam.size()!=0){
            return new ReturnRes(true, new PageInfo<>(raceVmOfTeam), "查询成功");
        }
        //获取个人的kali服务器
         return new ReturnRes(false, "暂无服务器");
    }

    @Override
    public ReturnRes submitApplyRaceVm(String name, Integer rid) {
        try {
            //先判断是不是队长

            String tcaptain= teamMapper.getTcaptain(userMapper.getTeanNameByName(name));
            String teanName=userMapper.getTeanNameByName(name);
           Integer num= raceMapper.getNumRaceMark(rid,teanName);
           if(num>0){
               return new ReturnRes(false, "本小组已失去参赛资格");
           }
            String race=raceMapper.getRaceName(rid);
            int count= vmMapper.getVMCountOfRace(race,teanName);
            if(count>0){
                return new ReturnRes(false, "一组同一时间仅能申请一组虚拟资源");
            }

            if(tcaptain.equals(name)){
                //获得一个空闲资源
                int proxy=vmMapper.getFreeProxy(race);
                if(proxy!=0){
                    vmMapper.submitApplyRaceVm(proxy,teanName,race);
                    List<String> vmIDs=vmMapper.getVmIdsofTeam(teanName);
                    for(int i =0;i<vmIDs.size();i++){
                        vmMapper.setFlagToTeam(vmIDs.get(i),teanName,rid);
                    }
                    return new ReturnRes(true, "申请成功");
                }else {
                    return new ReturnRes(false, "资源不足，请联系老师");
                }

            }
        }catch (Exception e){
        e.printStackTrace();
        }
              return new ReturnRes(false, "申请失败,可能资源不足,请联系老师");
       /* VmMapper.submitApplyRaceVm(name,rid);*/
    }

    @Override
    public ReturnRes submitApplyRaceVmClient(String name, Integer rid) {

        String race=raceMapper.getRaceName(rid);
        int count= vmMapper.getClientVMCountOfUser(race,name);
        if(count>0){
            return new ReturnRes(false, "客户机仅限一人一个");
        }
        Integer proxy=vmMapper.getFreeClientProxy(race);
        if(proxy!=null){
            vmMapper.getClientVMOfUser(race,name,proxy);
            return new ReturnRes(true, "申请成功");
        }else {
            return new ReturnRes(false, "此比赛客户机不足");
        }
    }

    @Override
    public ReturnRes createClientVm(Integer rId, Integer num) {

        //设置实例的可使用时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date()); // 设置当前时间
        int timeNum=raceMapper.getVmTimeByRid(rId);
        calendar.add(Calendar.HOUR_OF_DAY, timeNum); // 添加两个小时
        Date deadTime = calendar.getTime(); // 获取修改后的时间
        Integer clientId=raceMapper.getClientId(rId);

        System.err.println("开始创建");
        //查询映射
        String race=raceMapper.getRaceName(rId);

        for (int i=0;i<num;i++){
            //名称随机数
            Integer RandomNum= new Random().nextInt(10000);
            //每次寻找实例数量最少的openstack服务器 进行创建
            OpenStack openstack= cloudMapper.getMinVmNumofOpenstack();
            String network="public";//使用public网络
            //创建每组的靶机

                String flavor=imageMapper.getFlavorofVM(clientId);//查询镜像对应的实例类型
                //获得镜像名称
                String victim= imageMapper.getImageName(clientId);
                RaceVm raceVm = CloudUtils.createClientVm(openstack,victim,RandomNum,network,flavor,race);
                raceVm.setType(victim+"-client");
                raceVm.setOpenstackIP(openstack.getOpenstackIP());
                raceVm.setDeadTime(deadTime);
                raceMapper.insertRaceVm(raceVm);
                //存入数据库中
            System.out.println("存入数据库中："+raceVm);
                cloudMapper.updatecountVmOfOpenstack(openstack.getOpenstackIP());
        }
        System.err.println("结束创建");
        return new ReturnRes(true, "实例创建成功");
    }

    @Override
    public ReturnRes releaseRaceVm(String name, Integer rid) {

        String teamName=teamMapper.getTeamName(name);
        String tcaptain = teamMapper.getTcaptain(teamName);
        //释放用户的客户机器
            raceMapper.releaseRaceVmofUser(raceMapper.getRaceName(rid),name);

        if(tcaptain.equals(name)){

            List<VMservice> vmIDs = raceMapper.getRaceVmvmId(raceMapper.getRaceName(rid), teamName);
            if(vmIDs!=null){
                //释放小组的虚拟资源
                raceMapper.releaseRaceVm(teamName,raceMapper.getRaceName(rid));
                //将其加入放弃比赛的名单中
                raceMapper.inserRaceMark(rid,teamName);

                for(int i=0;i<vmIDs.size();i++){
                    //删除指定的vmID
                    CloudUtils.deleteVm(cloudMapper.getOpenstackByopenstackIP(  vmIDs.get(i).getOpenstackIP()),vmIDs.get(i).getVmID()  );
                    raceMapper.removeRaceVm(vmIDs.get(i).getVmID());
                    //删除这个虚拟对应的flag
                    raceMapper.deleteFlags(vmIDs.get(i).getVmID());
                }
                return new ReturnRes(true,"资源释放成功,已自动放弃当前比赛");
            }
        }
        return new ReturnRes(true,"资源释放成功");
    }

    @Override
    public ReturnRes searchRaceByPage(String key, String value, int pageNum, int pageSize) {

        PageHelper.startPage(pageNum, pageSize);
        String[] whiteList = new String[]{"rid", "rname"};
        if (CommonUtil.strArrayIsHave(whiteList, key)) {
            List<Race> raceList = raceMapper.searchRaceForAdmin(key, "%" + value + "%");
            if (raceList != null) {
                return new ReturnRes(true, new PageInfo<>(raceList), "查询成功");
            } else {
                return new ReturnRes(false, "查询失败");
            }
        } else {
            return new ReturnRes(false, "师傅请勿尝试不安全的参数");
        }

    }

    @Override
    public ReturnRes searchRaceVm(String key, String value, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        String[] whiteList = new String[]{"proxyNum", "race","team"};
        if (CommonUtil.strArrayIsHave(whiteList, key)) {
            List<VMservice> vmList = raceMapper.searchRaceVmForAdmin(key, "%" + value + "%");
            if (vmList != null) {
                return new ReturnRes(true, new PageInfo<>(vmList), "查询成功");
            } else {
                return new ReturnRes(false, "查询失败");
            }
        } else {
            return new ReturnRes(false, "师傅请勿尝试不安全的参数");
        }
    }

    @Override
    public ReturnRes searchFlagLog(String key, String value, int pageNum, int pageSize) {

        PageHelper.startPage(pageNum, pageSize);
        String[] whiteList = new String[]{"user", "result"};
        if (CommonUtil.strArrayIsHave(whiteList, key)) {
            List<FlagLog>  flagLogList = raceMapper.searchFlagLog(key, "%" + value + "%");
            if (flagLogList != null) {
                return new ReturnRes(true, new PageInfo<>(flagLogList), "查询成功");
            } else {
                return new ReturnRes(false, "查询失败");
            }
        } else {
            return new ReturnRes(false, "师傅请勿尝试不安全的参数");
        }
    }

    @Override
    public ReturnRes getFlagofTeam(Integer rid, Integer pageSize, Integer pageNum) {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Date deadTime=raceMapper.getDeadTime(rid);
        String team=teamMapper.getTeamName(authentication.getName());
        PageHelper.startPage(pageNum, pageSize);
        List<VmFlag> vmFlags = raceMapper.getFlagofTeam(team,rid,deadTime);
        if (vmFlags != null) {
            return new ReturnRes(true, new PageInfo<>(vmFlags), "查询成功");
        }
        return new ReturnRes(false, "查询失败");
    }

    @Override
    public ReturnRes getFlagofvM(int pageSize, int pageNum) {
        PageHelper.startPage(pageNum, pageSize);
        List<VmFlag> vmFlagList = raceMapper.getFlagofvM();

        if (vmFlagList != null) {
            return new ReturnRes(true, new PageInfo<>(vmFlagList), "查询成功");
        }
        return new ReturnRes(false, "查询失败");
    }

    @Override
    public ReturnRes searchFlagofVm(String key, String value, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        String[] whiteList = new String[]{"team", "race"};
        if (CommonUtil.strArrayIsHave(whiteList, key)) {
            List<VmFlag>  vmFlagList = raceMapper.searchFlagofVm(key, "%" + value + "%");
            if (vmFlagList != null) {
                return new ReturnRes(true, new PageInfo<>(vmFlagList), "查询成功");
            } else {
                return new ReturnRes(false, "查询失败");
            }
        } else {
            return new ReturnRes(false, "师傅请勿尝试不安全的参数");
        }
    }


    @Override
    public int removeRacebyId(Integer rid) {
       return  raceMapper.removeByRid(rid);
    }
    @Override
    public ReturnRes getRaceInfoById(int rid) {
        Race race = raceMapper.getRaceInfoById(rid);

        if (race != null) {
            return new ReturnRes(true, race, "查询成功");
        } else {
            return new ReturnRes(false, "查询失败");
        }
    }

    @Override
    public ReturnRes getAllparticipants(Integer rid, Integer pageSize, Integer pageNum) {

        PageHelper.startPage(pageNum, pageSize);
        List<RaceParticipant> raceParticipants = raceParticipantMapper.getAllparticipants(rid);
        if (raceParticipants != null) {
            return new ReturnRes(true, new PageInfo<>(raceParticipants), "查询成功");
        }
        return new ReturnRes(false, "查询失败");
    }

    @Override
    public ReturnRes getCurrentRanking(Integer rid ) {
        String race=raceMapper.getRaceName(rid);
        PageHelper.startPage(1, 30);
        List<TeamRank> teamRanks = raceParticipantMapper.getCurrentRanking(rid);
        if (teamRanks != null) {
           for (int i=0;i<teamRanks.size();i++){
               teamRanks.get(i).setRank(i+1);
           }

            return new ReturnRes(true, new PageInfo<>(teamRanks), "查询成功");
        }
        return new ReturnRes(false, "查询失败");
    }
    @Autowired
    LogMapper logMapper;
    @Override
    public ReturnRes submitRaceFlag(String name, Integer rid, String flag) {

        String teamName=userMapper.getTeanNameByName(name);
        if(teamName==null){
            return new ReturnRes(false, "请优先组队");

        }
        //不能提交本组的flag
        int num=raceMapper.getFlagOfOurTeam(rid,teamName,flag);

        if(num>=1){
            return new ReturnRes(false, "请勿提交本组flag");
        }
        int mark=raceMapper.getFlagMark(teamName,flag, rid);
        if(mark>=1){
            return new ReturnRes(false, "请勿重复提交flag");
        }
        int count=raceMapper.attackVM(rid,flag);
        //获得衰减分数
        int reduceSpeend=raceMapper.getReduceSpeedById(rid);
        if(count>=1){
            raceMapper.addFlagMark(teamName,flag,rid);
            int score=0;
            //获得被攻击次数，计算衰减速度
          int attackCount =  raceMapper.getAttackCount(flag);
          String s="";
            OperationLog operationLog = new OperationLog();
            operationLog.setUsername(name);
            operationLog.setOperateTime(new Date());

            if(attackCount==0){
                System.out.println(name+"触发一血 flag:"+flag);
                score=130;
                s="拿下一血!!!";
                operationLog.setAction(s);
                operationLog.setParams(flag);
            }else if(attackCount==1){
                score=120;
                System.out.println(name+"触发二血 flag:"+flag);
                s="拿下二血!!!";
                operationLog.setAction(s);
                operationLog.setParams(flag);
            }else if(attackCount==3){
                score=110;
                System.out.println(name+"触发三血 flag:"+flag);
                s="拿下三血!!!";
                operationLog.setAction(s);
                operationLog.setParams(flag);
                logMapper.insertSysLog(operationLog);
            }else {
                score=raceMapper.getFlagScore(flag)-attackCount*reduceSpeend;
                s="拿下Flag!!!";
            }
            if (score<=0){
                score=10;
            }
            //修改被攻击次数
            raceMapper.updateAttackCount(flag);
            raceMapper.addScoreToTeam(teamName,score,rid);
            raceMapper.updateFlag(name,flag,new Date(),"正确");
            return new ReturnRes(true, s);
        }else {
            raceMapper.updateFlag(name,flag,new Date(),"错误");
            return new ReturnRes(false, "flag错误");
        }
    }


    @Override
    public ReturnRes addRace(Race race,Integer SceneId) {
       int exit= raceMapper.judgeExitsRace(race.getRname());
       if(exit>0){
           return new ReturnRes(false, "比赛已存在");
       }
        Date today = new Date();
        Date startTime = race.getCtime();
        Date deadTime = race.getDtime();
        if (startTime.compareTo(today)<0&&deadTime.compareTo(today)>0) {
            race.setStatus(1);
        } else {
            race.setStatus(0);
        }
        int count = raceMapper.insertRace(race);
        sceneMapper.InsertScene(raceMapper.getRaceIdByName(race.getRname()),SceneId);
      if(count>0){
          return new ReturnRes(true, "添加成功");
      }
        return new ReturnRes(false, "添加失败");
    }

    @Override
    public ReturnRes createRaceVm(Integer rId, int count) {
        //设置实例的可使用时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date()); // 设置当前时间
        int timeNum=raceMapper.getVmTimeByRid(rId);
        calendar.add(Calendar.HOUR_OF_DAY, timeNum); // 添加两个小时
        Date deadTime = calendar.getTime(); // 获取修改后的时间

        System.err.println("开始创建");
        //查询映射
        Integer sId=sceneMapper.getRaceScenesByRaceId(rId);
        List<Integer> victimIds=sceneMapper.getVictimIdsBysId(sId);


        //创建实例 例如五个队伍 就创建5个
        for (int i=0;i<count;i++){
            //名称随机数
            Integer RandomNum= new Random().nextInt(10000);
            //每次寻找实例数量最少的openstack服务器 进行创建
            OpenStack openstack= cloudMapper.getMinVmNumofOpenstack();
            String network="public";//使用public网络
            String race=raceMapper.getRaceName(rId);
            //创建每组的靶机
            for (Integer victimId:victimIds) {

                String flavor=imageMapper.getFlavorofVM(victimId);//查询镜像对应的实例类型
                //获得镜像名称
                String victim= imageMapper.getImageName(victimId);
                Integer flagNum=imageMapper.getFlagNum(victim);
                //创建靶机
                //生成flag数量 设置元数据
                List<String> flags=new ArrayList<>();

                for(int q=0;q<flagNum;q++){
                    String flag=CloudUtils.getFlag();
                    flags.add(flag);
                }
                RaceVm raceVm = CloudUtils.createRaceVms(race, openstack, victim, RandomNum, network, flavor,flags);
                raceVm.setType(victim);
                raceVm.setOpenstackIP(openstack.getOpenstackIP());
                raceVm.setDeadTime(deadTime);
                raceMapper.insertRaceVm(raceVm);
                for(int q=0;q<flagNum;q++){
                    raceMapper.inserFlag(raceMapper.getRaceId(race),raceVm.getVmID(),flags.get(q),raceMapper.getRaceFlagScore(race));
                }

                //存入数据库中

                cloudMapper.updatecountVmOfOpenstack(openstack.getOpenstackIP());
            }
        }
        System.err.println("结束创建");
        return new ReturnRes(true, "实例创建成功");
    }

    @Override
    public ReturnRes getRaceScenes() {

        return  new ReturnRes(true, sceneMapper.getRaceScenes());
    }

    @Override
    public ReturnRes getAllRaceVms(int pageSize, int pageNum) {
        PageHelper.startPage(pageNum, pageSize);
        List<VMservice> raceVms = raceMapper.getAllRaceVms();
        if (raceVms != null) {
            return new ReturnRes(true, new PageInfo<>(raceVms), "查询成功");
        }

        return new ReturnRes(false, "查询失败");
    }

/*    @Override
    public ReturnRes getRaceVmsForTeam(String id, String name) {

        //race ID    同学名称
        raceMapper.getRaceVmsForTeam(raceMapper.getRaceName(id),userMapper.getTeanNameByName(name));
        return null;
    }*/

    @Override
    public ReturnRes getSubmitFlagLogs(int pageSize, int pageNum) {

        PageHelper.startPage(pageNum, pageSize);
        List<FlagLog> flagLogs = raceMapper.getSubmitFlagLogs();
        if (flagLogs != null) {
            return new ReturnRes(true, new PageInfo<>(flagLogs), "查询成功");
        }

        return new ReturnRes(false, "查询失败");
    }

    @Override
    public ReturnRes getTeamRanking(int pageSize, int pageNum,Integer rid) {
        PageHelper.startPage(pageNum, pageSize);
        List<TeamRank> raceRanking = raceParticipantMapper.getCurrentRanking(rid);
        System.err.println(raceRanking);
        if (raceRanking != null) {
            for (int i=0;i<raceRanking.size();i++){
                raceRanking.get(i).setRank(pageSize*(pageNum-1)+i+1);
            }
            return new ReturnRes(true, new PageInfo<>(raceRanking), "查询成功");
        }
        return new ReturnRes(false, "查询失败");
    }

    @Override
    public ReturnRes removeRankingOfRace(String rid) {

         int count =raceMapper.removeRankingOfRace(rid);


        if(   count >=1){
            return new ReturnRes(true, "删除成功");
        }
        return new ReturnRes(false, "系统服务出现故障");
    }
    @Override
    public ReturnRes getRacevmCount() {
        //先查找出所有的比赛
        List<String> races=raceMapper.getAllraces();
        List<VmCount>  vmCountList=new ArrayList<>();
        for (int i=0;i<races.size();i++){
            VmCount vmCount = new VmCount();
            int vmSum=raceMapper.getVmSumofRace(races.get(i));
            int usingCount=raceMapper.getVmUsingofRace(races.get(i));
            vmCount.setSum(vmSum);
            vmCount.setUsing(usingCount);
            vmCount.setName(races.get(i));
            vmCountList.add(vmCount);
        }

        if(   vmCountList.size() >=1){
            return new ReturnRes(true, new PageInfo<>(vmCountList), "查询成功");
        }
        return new ReturnRes(false, "暂无查找到资源");
    }

    @Override
    public ReturnRes updateRace(Race race, Integer sceneId) {


            int count = raceMapper.updateRace(race);
            if(count>0){

            }
        int count2 =  sceneMapper.updateRaceScene(race.getRid(), sceneId);

        if(count>0&&count2>0){
                return new ReturnRes(true, "更新成功");
            }
            return new ReturnRes(false, "添加失败");
        }

    @Override
    public ReturnRes getRaceInfo(int rid) {

            Race race = raceMapper.getRaceInfoById(rid);
            Integer sceneId=sceneMapper.getRaceScenesByRaceId(rid);
            List<Object> lists=new ArrayList<>();
            lists.add(race);
            lists.add(sceneId);
            if (race != null) {
                return new ReturnRes(true, lists, "查询成功");
            } else {
                return new ReturnRes(false, "查询失败");
        }
    }
    @Autowired
    ExperimentsMapper experimentsMapper;
    @Override
    public ReturnRes releaseRaceAllVms() {

        List<VMservice> vmList= raceMapper.findAllRaceVms();
        for (int i = 0; i <vmList.size() ; i++) {
            CloudUtils.deleteVm(cloudMapper.getOpenstackByopenstackIP(vmList.get(i).getOpenstackIP()), vmList.get(i).getVmID());
            int count =experimentsMapper.removeVmById(vmList.get(i).getVmID());
        }

        return new ReturnRes(true,  "释放成功");
    }

}
